home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
iritsm3s.zip
/
CAGDCMRG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-02
|
11KB
|
353 lines
/******************************************************************************
* CagdCMrg.c - Curve/Point merging routines. *
*******************************************************************************
* Written by Gershon Elber, May 91. *
******************************************************************************/
#include "string.h"
#include "cagd_loc.h"
static void CopyCrvOnCrv(CagdCrvStruct *DestCrv, int Index,
CagdCrvStruct *SrcCrv);
static void InterpolateLinearSeg(CagdCrvStruct *Crv, int Index1, int Index2);
/******************************************************************************
* Merge two curves. *
******************************************************************************/
CagdCrvStruct *CagdMergeCrvCrv(CagdCrvStruct *Crv1, CagdCrvStruct *Crv2)
{
CagdBType CrvsSharePt,
Crv1New = FALSE,
Crv2New = FALSE,
IsRational1 = CAGD_IS_RATIONAL_CRV(Crv1),
IsRational2 = CAGD_IS_RATIONAL_CRV(Crv2);
int Length, Order,
Order1 = Crv1 -> Order,
Order2 = Crv2 -> Order,
Len1 = Crv1 -> Length,
Len2 = Crv2 -> Length,
MaxCoord1 = CAGD_NUM_OF_PT_COORD(Crv1 -> PType),
MaxCoord2 = CAGD_NUM_OF_PT_COORD(Crv2 -> PType);
CagdRType E3Pt1[3], E3Pt2[3];
CagdPointType CrvPType = CAGD_PT_E2_TYPE;
CagdCrvStruct *Crv;
/* Make orders compatible: */
if (Order1 < Order2) {
for (; Order1 < Order2; Order1++) {
Crv = CagdCrvDegreeRaise(Crv1);
if (Crv1New)
CagdCrvFree(Crv1);
Crv1 = Crv;
Len1 = Crv1 -> Length;
Crv1New = TRUE;
}
}
else if (Order2 < Order1) {
for (; Order2 < Order1; Order2++) {
Crv = CagdCrvDegreeRaise(Crv2);
if (Crv2New)
CagdCrvFree(Crv2);
Crv2 = Crv;
Len2 = Crv2 -> Length;
Crv2New = TRUE;
}
}
Order = Order1;
/* Verify curve geometric types. */
switch (Crv1 -> GType) {
case CAGD_CBEZIER_TYPE:
Crv = CnvrtBezier2BsplineCrv(Crv1);
if (Crv1New)
CagdCrvFree(Crv1);
Crv1 = Crv;
Crv1New = TRUE;
break;
case CAGD_CBSPLINE_TYPE:
break;
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
break;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
break;
}
switch (Crv2 -> GType) {
case CAGD_CBEZIER_TYPE:
Crv = CnvrtBezier2BsplineCrv(Crv2);
if (Crv2New)
CagdCrvFree(Crv2);
Crv2 = Crv;
Crv2New = TRUE;
break;
case CAGD_CBSPLINE_TYPE:
break;
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
break;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
break;
}
/* Compute curve point types. */
CrvPType = CAGD_MAKE_PT_TYPE(IsRational1 || IsRational2,
MAX(MaxCoord1, MaxCoord2));
/* Figure out if end point of Crv1 is equal to start point of Crv2 and */
/* Compute the length of the resulting curve accordingly. */
/* If the same point, then the result can omit one copy and therefore */
/* has Len1 + Len2 - 1 Ctl points. If however a linear segment should be */
/* introduced between the two curves, it should hold Order colinear pts */
/* including 2 end points shared with curves or Order - 2 new pts. */
CagdCoerceToE3(E3Pt1, Crv1 -> Points, Len1 - 1, Crv1 -> PType);
CagdCoerceToE3(E3Pt2, Crv2 -> Points, 0, Crv2 -> PType);
CrvsSharePt = APX_EQ(E3Pt1[0], E3Pt2[0]) &&
APX_EQ(E3Pt1[1], E3Pt2[1]) &&
APX_EQ(E3Pt1[2], E3Pt2[2]);
Length = CrvsSharePt ? Len1 + Len2 - 1 : Len1 + Len2 + Order - 2;
Crv = BspCrvNew(Length, Order, CrvPType);
CopyCrvOnCrv(Crv, 0, Crv1);
CopyCrvOnCrv(Crv, Length - Len2, Crv2);
InterpolateLinearSeg(Crv, Len1 - 1, Length - Len2);
/* Update the knot vector. We assume open end condition here... */
GEN_COPY(Crv -> KnotVector, Crv1 -> KnotVector,
(Len1 + Order1 - 1) * sizeof(CagdRType));
if (CrvsSharePt) {
GEN_COPY(&Crv -> KnotVector[Len1 + Order1 - 1],
&Crv2 -> KnotVector[Order2], Len2 * sizeof(CagdRType));
BspKnotAffineTrans(&Crv -> KnotVector[Len1 + Order1 - 1],
Len2,
Crv -> KnotVector[Len1 + Order1 - 2] -
Crv2 -> KnotVector[0],
1.0);
}
else {
GEN_COPY(&Crv -> KnotVector[Len1 + Order1 - 1],
&Crv2 -> KnotVector[1],
(Len2 + Order2 - 1) * sizeof(CagdRType));
BspKnotAffineTrans(&Crv -> KnotVector[Len1 + Order1 - 1],
Len2 + Order2 - 1,
Crv -> KnotVector[Len1 + Order1 - 2] -
Crv -> KnotVector[Len1 + Order1 - 1] + 1.0,
1.0);
}
if (Crv1New)
CagdCrvFree(Crv1);
if (Crv2New)
CagdCrvFree(Crv2);
return Crv;
}
/******************************************************************************
* Merge a curve and a point. *
******************************************************************************/
CagdCrvStruct *CagdMergeCrvPt(CagdCrvStruct *Crv, CagdPtStruct *Pt)
{
CagdBType
CrvNew = FALSE,
IsRational = CAGD_IS_RATIONAL_CRV(Crv);
int i, NewLen, NewMaxCoord,
Order = Crv -> Order,
Len = Crv -> Length,
PtMaxCoord = APX_EQ(Pt -> Pt[2], 0.0) ? 2 : 3,
MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
CagdPointType
CrvPType = CAGD_PT_E2_TYPE;
CagdRType t, **Points;
CagdCrvStruct *NewCrv;
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
Crv = CnvrtBezier2BsplineCrv(Crv);
CrvNew = TRUE;
case CAGD_CBSPLINE_TYPE:
break;
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
break;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
break;
}
/* Compute curve point types. */
NewMaxCoord = MAX(PtMaxCoord, MaxCoord);
CrvPType = CAGD_MAKE_PT_TYPE(IsRational, NewMaxCoord);
/* A linear segment is added at the end with Order colinear pts. */
/* However since first point is curve last point, only Order - 1 new. */
NewLen = Len + Order - 1;
NewCrv = BspCrvNew(NewLen, Order, CrvPType);
Points = NewCrv -> Points;
CopyCrvOnCrv(NewCrv, 0, Crv);
for (i = 1; i <= NewMaxCoord; i++) Points[i][NewLen - 1] = Pt -> Pt[i - 1];
if (IsRational) Points[W][NewLen - 1] = 1.0;
InterpolateLinearSeg(NewCrv, Len - 1, NewLen - 1);
/* Update the knot vector. We assume open end condition here... */
GEN_COPY(NewCrv -> KnotVector, Crv -> KnotVector,
(Len + Order - 1) * sizeof(CagdRType));
t = Crv -> KnotVector[Len + Order - 1] + 1.0;
for (i = Len + Order - 1; i < NewLen + Order; i++)
NewCrv -> KnotVector[i] = t;
if (CrvNew)
CagdCrvFree(Crv);
return NewCrv;
}
/******************************************************************************
* Merge a point and a curve. *
******************************************************************************/
CagdCrvStruct *CagdMergePtCrv(CagdPtStruct *Pt, CagdCrvStruct *Crv)
{
CagdBType
CrvNew = FALSE,
IsRational = CAGD_IS_RATIONAL_CRV(Crv);
int i, NewLen, NewMaxCoord,
Order = Crv -> Order,
Len = Crv -> Length,
PtMaxCoord = APX_EQ(Pt -> Pt[2], 0.0) ? 2 : 3,
MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
CagdPointType
CrvPType = CAGD_PT_E2_TYPE;
CagdRType t, **Points;
CagdCrvStruct *NewCrv;
switch (Crv -> GType) {
case CAGD_CBEZIER_TYPE:
Crv = CnvrtBezier2BsplineCrv(Crv);
CrvNew = TRUE;
break;
case CAGD_CBSPLINE_TYPE:
break;
case CAGD_CPOWER_TYPE:
FATAL_ERROR(CAGD_ERR_POWER_NO_SUPPORT);
break;
default:
FATAL_ERROR(CAGD_ERR_UNDEF_CRV);
break;
}
/* Compute curve point types. */
NewMaxCoord = MAX(PtMaxCoord, MaxCoord);
CrvPType = CAGD_MAKE_PT_TYPE(IsRational, NewMaxCoord);
/* A linear segment is added at the end with Order colinear pts. */
/* However since first point is curve last point, only Order - 1 new. */
NewLen = Len + Order - 1;
NewCrv = BspCrvNew(NewLen, Order, CrvPType);
Points = NewCrv -> Points;
CopyCrvOnCrv(NewCrv, Order - 1, Crv);
for (i = 1; i <= NewMaxCoord; i++) Points[i][0] = Pt -> Pt[i - 1];
if (IsRational) Points[W][0] = 1.0;
InterpolateLinearSeg(NewCrv, 0, Order - 1);
/* Update the knot vector. We assume open end condition here... */
GEN_COPY(&NewCrv -> KnotVector[Order], &Crv -> KnotVector[1],
(Len + Order - 1) * sizeof(CagdRType));
t = Crv -> KnotVector[0] - 1.0;
for (i = 0; i < Order; i++)
NewCrv -> KnotVector[i] = t;
if (CrvNew)
CagdCrvFree(Crv);
return NewCrv;
}
/******************************************************************************
* Merge two points into a linear Bezier curve. *
******************************************************************************/
CagdCrvStruct *CagdMergePtPt(CagdPtStruct *Pt1, CagdPtStruct *Pt2)
{
CagdPointType
CrvPType = APX_EQ(Pt1 -> Pt[2], 0.0) && APX_EQ(Pt2 -> Pt[2], 0.0) ?
CAGD_PT_E2_TYPE : CAGD_PT_E3_TYPE;
CagdCrvStruct
*Crv = BzrCrvNew(2, CrvPType);
CagdRType
**Points = Crv -> Points;
Points[X][0] = Pt1 -> Pt[0];
Points[X][1] = Pt2 -> Pt[0];
Points[Y][0] = Pt1 -> Pt[1];
Points[Y][1] = Pt2 -> Pt[1];
if (CrvPType == CAGD_PT_E3_TYPE) {
Points[Z][0] = Pt1 -> Pt[2];
Points[Z][1] = Pt2 -> Pt[2];
}
return Crv;
}
/******************************************************************************
* Copy SrcCrv into DestCrv at point index Index. *
* DestCrv PType is assumed to hold Src PType. *
******************************************************************************/
static void CopyCrvOnCrv(CagdCrvStruct *DestCrv, int Index,
CagdCrvStruct *SrcCrv)
{
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_CRV(SrcCrv);
int i, j,
Len = SrcCrv -> Length,
MaxCoord = CAGD_NUM_OF_PT_COORD(SrcCrv -> PType);
CagdRType
**SrcPoints = SrcCrv -> Points,
**DestPoints = DestCrv -> Points;
for (i = IsNotRational; i <= MaxCoord; i++)
GEN_COPY(&DestPoints[i][Index], SrcPoints[i],
Len * sizeof(CagdRType));
/* Fix the weights if source did not have them. */
if (IsNotRational && CAGD_IS_RATIONAL_CRV(DestCrv))
for (i = Index; i < Index + Len; i++)
DestPoints[W][i] = 1.0;
/* Fix the higher coordinates (by coercing them to zero. */
for (i = MaxCoord + 1; i < CAGD_NUM_OF_PT_COORD(DestCrv -> PType); i++)
for (j = Index; j < Index + Len; j++)
DestPoints[i][j] = 0.0;
}
/******************************************************************************
* Linearly interpolate between the Crv points indices Index1 and Index2 *
******************************************************************************/
static void InterpolateLinearSeg(CagdCrvStruct *Crv, int Index1, int Index2)
{
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
int i, j,
DIndex = Index2 - Index1,
MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
CagdRType
**Points = Crv -> Points;
if (DIndex < 2) return; /* No middle points to interp. */
for (i = Index1 + 1; i < Index2; i++) {
CagdRType
t1 = ((CagdRType) (i - Index1)) / DIndex,
t2 = 1.0 - t1;
for (j = IsNotRational; j <= MaxCoord; j++)
Points[j][i] = t2 * Points[j][Index1] + t1 * Points[j][Index2];
}
}